/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package gui;

import explorer.*;
import explorer.FileExplorerController;
import explorer.FileModel;
import explorer.FileRenderer;
import explorer.FileTableModel;
import explorer.FileTools;
import explorer.FileTreeModel;
import explorer.RightClickPopupMenuExplorer;
import gui.AbstractModule;
import gui.MainWindow;
import gui.graphicals.ToolBar;
import gui.multimedia.MultimediaView;
import java.awt.Color;
import java.awt.Component;
import java.awt.Desktop;
import java.awt.event.*;
import java.io.File;
import java.io.IOException;
import java.util.Comparator;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.*;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.filechooser.FileSystemView;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableModel;
import javax.swing.table.TableRowSorter;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;
import technical.ClInit;

public class FileExplorerView extends AbstractModule implements ActionListener, MouseListener, TreeSelectionListener {

    private FileExplorerController _myController;
    private static String __homeDirectory = ClInit.getExplorerDefaultHomePage();
    private FileTreeModel _model;
    private JTree _tree;
    private JSplitPane _mainFrame;
    private JTextArea _infos;
    private JTextField _myPathField;
    private JPanel _panel;
    private JList _fileList;
    private JTable _fileTable;
    
    
    private RightClickPopupMenuExplorer _pMenu = new RightClickPopupMenuExplorer();
    
    public FileExplorerView(MainWindow mainWindow) {
        super(mainWindow);
    }

    @Override
    public void initController() {
        _myController = FileExplorerController.getInstance(this);
        _myController.setRoot(__homeDirectory);
    }

    @Override
    protected ToolBar getToolBar() {

        ToolBar tb = new ToolBar();
        ActionListener myActList = this;

        tb.makeButton("back.png",
                "BACK",
                "Retour en arrière",
                "BACK",
                myActList);

        tb.makeButton("forward.png",
                "FORWARD",
                "Continue la navigation",
                "FORWARD",
                myActList);

        tb.addSeparator();

        tb.makeButton("refresh.png",
                "REFRESH",
                "Rafraichir la page",
                "REFRESH",
                myActList);

        tb.addSeparator();

        tb.makeButton("",
                "Nouveau dossier",
                "Créer un nouveau dossier",
                "Nouveau dossier",
                myActList);

        tb.makeButton("", "Supprimer", "Supprimer le dossier sélectionné", "Supprimer", myActList);

        tb.makeButton("",
                "Renommer",
                "Renommer le dossier",
                "Renommer",
                myActList);

        _myPathField = new JTextField(__homeDirectory);
        tb.add(_myPathField);

        tb.makeButton("go.png",
                "GO",
                "C'est parti",
                "GO",
                myActList);

        return tb;
    }

    @Override
    protected JComponent getMainFrame() {
        
        _mainFrame = new JSplitPane();

        _model = new FileTreeModel(new FileModel(_myController.getRoot()));
        _tree = new JTree(_model);
        _tree.setCellRenderer(new FileRenderer());
        _tree.addTreeSelectionListener(this);
        _tree.addMouseListener(this);
        
        //Keyboard shortcuts
        _tree.addKeyListener(new KeyListener() {

            @Override
            public void keyTyped(KeyEvent e) {
            }

            @Override
            public void keyPressed(KeyEvent e) {

                File node = new File(((FileModel) _tree.getSelectionPath().getLastPathComponent()).getPath());
                String pathToRefresh = node.getAbsolutePath();
                
                if (e.getKeyCode() == KeyEvent.VK_F2) {

                    String name = JOptionPane.showInputDialog("Nouveau nom ?");
                    _myController.renameFolder(node, name);
                    pathToRefresh = node.getParent();
                }

                else if (e.getModifiers() == InputEvent.CTRL_MASK && e.getKeyCode() == KeyEvent.VK_N) {

                    String name = JOptionPane.showInputDialog("Nouveau dossier");
                    _myController.createFolder(name, node.getAbsolutePath());
                }

                else if (e.getKeyCode() == KeyEvent.VK_F5) {
                }

                updateAll(pathToRefresh);
            }

            @Override
            public void keyReleased(KeyEvent e) {
            }
        });

        _tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);

        _infos = new JTextArea();
        _infos.setEditable(false);
        _infos.setLineWrap(true);
        _infos.setWrapStyleWord(true);

        _mainFrame.setLeftComponent(new JScrollPane(_tree));
        _mainFrame.setRightComponent(getRightContent());
        _mainFrame.setDividerLocation(250);
        _mainFrame.setBackground(Color.white);

        return _mainFrame;
    }

    private JScrollPane getRightContent() {

        JScrollPane sp = new JScrollPane(buildFileTable());
        sp.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
        sp.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
        
        updateRightContent(__homeDirectory);
        
        return sp;
    }
      
    private JTable buildFileTable() {
        
        _fileTable = new JTable(new FileTableModel(_myController.getFileModels(__homeDirectory)));
        _fileTable.addMouseListener(this);
        _fileTable.setAutoCreateRowSorter(true);
        _fileTable.setShowHorizontalLines(false);
        _fileTable.setShowVerticalLines(false);
      
        _fileTable.setDefaultRenderer(String.class, new DefaultTableCellRenderer() {
            
            @Override
            public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {

                super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);

                File file = new File(_myPathField.getText() + "/" + (String) value);
                FileSystemView sys = FileSystemView.getFileSystemView();

                try {
                    if (file.exists() && file != null) {
                        setIcon(sys.getSystemIcon(file));
                    }
                } catch (Exception ex) {

                }
                setText(file.getName());

                return this;
                }
        });
        
        _fileTable.getColumnModel().getColumn(2).setMaxWidth(20);
        _fileTable.getColumnModel().getColumn(3).setMaxWidth(100);
        
        
        
        _fileTable.setDefaultRenderer(Boolean.class, new DefaultTableCellRenderer() {
            
            @Override
            public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
                
                super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);

                Boolean bool = (Boolean) value;
                
                String imageName;
                
                if(bool){
                    imageName = "tick.png";
                } else {
                    imageName = "untick.gif";
                }
                
                setText("");
                setIcon(new ImageIcon(getClass().getResource("/drawable/" + imageName), imageName));
                setHorizontalAlignment(JLabel.CENTER);
                
                return this;
            }
            
        });
        
        
       _fileTable.setDefaultRenderer(Long.class, new DefaultTableCellRenderer() {
            
            @Override
            public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
                
                super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);

                Long size = (Long) value;
                
                String text;
                // Display right size (depends on the file size at the beginning)
                if (size >= 1024) {
                    size = size / 1024;
                    text = " ko";
                    if (size >= 1024) {
                        size = size / 1024;
                        text = " Mo";
                        if (size >= 1024) {
                            size = size / 1024;
                            text = " Go";
                        }
                    }
                } else {
                    text = " o";
                }
                
                setText(size + text);
                setHorizontalAlignment(JLabel.CENTER);
                
                return this;
            }
            
        });
        
       _fileTable.addKeyListener(new KeyListener() {

            @Override
            public void keyTyped(KeyEvent e) {
                throw new UnsupportedOperationException("Not supported yet.");
            }

            @Override
            public void keyPressed(KeyEvent e) {
                File tmp = new File(((FileTableModel) _fileTable.getModel()).getValueAt(_fileTable.getSelectedRow()).getPath());
                String pathToRefresh = tmp.getAbsolutePath();
                
                if (e.getKeyCode() == KeyEvent.VK_F2) {

                    String name = JOptionPane.showInputDialog("Nouveau nom ?");
                    _myController.renameFolder(tmp, name);
                    pathToRefresh = tmp.getParent();
                }

               if (e.getModifiers() == InputEvent.SHIFT_MASK && e.getKeyCode() == KeyEvent.VK_DELETE) {
                    try {
                        delete(tmp);
                    } catch (IOException ex) {
                        Logger.getLogger(FileExplorerView.class.getName()).log(Level.SEVERE, null, ex);
                    }
                }

                else if (e.getKeyCode() == KeyEvent.VK_F5) {
                }

                updateAll(pathToRefresh);
            }

            @Override
            public void keyReleased(KeyEvent e) {
                throw new UnsupportedOperationException("Not supported yet.");
            }
        });
       
        return _fileTable;
    }
    
    public void delete(File toDelete) throws IOException {
            if (toDelete.isFile()) {
                FileTools.removeFile(toDelete.getAbsolutePath(), "/");
            } else {
                FileTools.deleteDirectory(new File(toDelete.getAbsolutePath()));
            }
    }
    
    private void updateTreeDisplay(JTree tree) {
        tree.updateUI();
    }
    
    private void updateRightContent(String path) {
        updateRightContent(new FileTableModel(_myController.getFileModels(path)));
    }
    
    private void updateRightContent(FileTableModel ftm) {
        _fileTable.setModel(ftm);
        TableRowSorter<TableModel> sorter = new TableRowSorter<TableModel>(_fileTable.getModel());
        sorter.setSortsOnUpdates(true);
        
        //sorter.setSortable(2, false); // Disabled sort of a column
        
        // Other method to sort a column
        sorter.setComparator(1, new Comparator<Long>() {
            
            @Override
            public int compare(Long o1, Long o2) {
                return o1.compareTo(o2);
            }
            
        });
        
        _fileTable.setRowSorter(sorter);
    }

    private void updateAll(String path) {
        updateTreeDisplay(_tree);
        updateRightContent(path);
    }

    @Override
    public void valueChanged(TreeSelectionEvent e) {
        TreePath path = e.getPath();
        File file = new File(((FileModel) path.getLastPathComponent()).getPath());
        
        _myPathField.setText(file.getPath());
        
        if (file.isDirectory()) {
            updateRightContent(file.getAbsolutePath());
        }
    }

    @Override
    public void actionPerformed(ActionEvent ae) {

        File node = new File(((FileModel) _tree.getSelectionPath().getLastPathComponent()).getPath());
        String pathToRefresh = node.getAbsolutePath();
        
        if (pathToRefresh == null) {
            return;
        }
        
        if (ae.getActionCommand().equalsIgnoreCase("Nouveau dossier")) {

            String name = JOptionPane.showInputDialog("Nouveau dossier");
            _myController.createFolder(name, node.getAbsolutePath());
        }

        if (ae.getActionCommand().equalsIgnoreCase("Supprimer")) {

            _myController.deleteFolder(node.getAbsolutePath());
            pathToRefresh = node.getParent();
        }

        if (ae.getActionCommand().equalsIgnoreCase("Renommer")) {

            String name = JOptionPane.showInputDialog("Nouveau nom ?");

            _myController.renameFolder(node, name);
            pathToRefresh = node.getParent();
        }

        // Refresh is automatic when action is performed
        if (ae.getActionCommand().equalsIgnoreCase("Refresh")) {
        }

        updateAll(pathToRefresh);
    }
    
    
    
    @Override
    public void mouseClicked(MouseEvent me) {

        // When double click on right panel
        if (me.getSource() == _fileTable && me.getClickCount() == 2) {
            
            File tmp = new File(((FileTableModel) _fileTable.getModel()).getValueAt(_fileTable.getSelectedRow()).getPath());
            
            if (tmp != null) {
                if (multimedia.MultimediaController.checkExtension(tmp.getAbsolutePath())) {
                    MultimediaView music = (MultimediaView) getMainWindow().getModule("MULTIMEDIA");
                    getMainWindow().changeModule("MULTIMEDIA");
                    music.launchNewSong(tmp.getAbsolutePath());
                    return;
                }
            }
        }
        
        
        // To open a file , doucle click on the right panel
        
        if (me.getSource() == _fileTable && me.getClickCount() == 2) {
            File tmp = new File(((FileTableModel) _fileTable.getModel()).getValueAt(_fileTable.getSelectedRow()).getPath());
            System.out.println("Runtime");
            if (tmp != null) {                
                // Checking that the class Desktop is actually supported
                if ( Desktop.isDesktopSupported() ) {
                    // Getting desktop instance : 
                    Desktop desktop = Desktop.getDesktop();
	
                    // Checking that the open function is actually supported :
                    if (desktop.isSupported(Desktop.Action.OPEN)) {
                        try {
                            // Finally, launching the associated application of the file we have double clicked on :
                            desktop.open(new File(tmp.getAbsolutePath()));
                        } catch (IOException ex) {
                            Logger.getLogger(FileExplorerView.class.getName()).log(Level.SEVERE, null, ex);
                        }
                    }
                }
            }
        }
        
        if (_tree.isSelectionEmpty()) {
            return;
        }

        File file = new File(((FileModel) _tree.getSelectionPath().getLastPathComponent()).getPath());

        if (me.getSource() == _tree && me.getClickCount() == 2) {
            if (file.isDirectory()) {
                updateRightContent(file.getAbsolutePath());
            }
        }
    }

    @Override
    public void mousePressed(MouseEvent me) {
        
        if (me.getSource() != _tree && me.getSource() != _fileTable) {
            return;
        }
        
        _pMenu.setSource(me.getSource());
        
        if (me.getButton() == MouseEvent.BUTTON3) { 
            _pMenu.setLocation(me.getXOnScreen(), me.getYOnScreen());
            _pMenu.setVisible(true);
        }
        if (me.getClickCount() == 1 && me.getButton() == MouseEvent.BUTTON1) {
            _pMenu.setVisible(false);
            
        }
        
        if (_pMenu.showHidden() != ((FileTableModel) _fileTable.getModel()).getIfIsHidden()) {
            FileTableModel ftm = new FileTableModel(_myController.getFileModels(_myPathField.getText()), _pMenu.showHidden());
            updateRightContent(ftm);
        }

    }         

    @Override
    public void mouseReleased(MouseEvent e) {

    }

    @Override
    public void mouseEntered(MouseEvent e) {

    }

    @Override
    public void mouseExited(MouseEvent e) {

    }
}
